import https = require('https');
import http = require('http');
import platform = require('../../common/baseCommon');
import urlExplain = require('url');
// import moduleName =require('../../common/moduleName');


let moduleName = 'platform';

@platform.addon("jsonRpc客户端", "jsonRpc客户端", moduleName)
export class jsonRpcClient extends platform.baseObject {

    authNeeded: boolean;
    protocol: string;
    user: string;
    password: string;
    host: string;
    port: number;
    agent: any;
    method: string;
    path: string;
    authData: string;

    constructor(options: any) {
        super();
        var options = options || {};
        this.authNeeded = false;
        this.protocol = options.protocol || 'http';//Either http or https
        this.user = options.user || null;
        this.password = options.password || null;
        this.host = options.host || '127.0.0.1';
        this.port = options.port || ((this.protocol === 'https') ? 8443 : 8080);
        this.agent = (this.protocol === 'https') ? https : http;
        this.method = options.method || "POST";
        this.path = options.path || '/';
        if (options && options.hasOwnProperty('user') && (options.hasOwnProperty('password') || options.hasOwnProperty('pass'))) {
            this.authNeeded = true;
            this.authData = options.user;
            if (options.hasOwnProperty('password')) {
                this.authData += ':' + options.password;
            }
            if (options.hasOwnProperty('pass')) {
                this.password = options.pass;
                this.authData += ':' + options.pass;
            }
        }
    }

    //生成随机数
    getRandomId() {
        return parseInt((Math.random() * 100000).toString());
    }


    /**
     * 远程调用
     * @param options 调用参数
     * @param callback 回调函数
     */
    call(options: any, callback: any) {
        //请求数据
        var requestData = {
            id: this.getRandomId().toString(),
            method: '',
            jsonrpc: '2.0',
            serviceName: '',
            params: [],
        };
        var params = [], method = '', jsonrpc = '2.0', id = this.getRandomId().toString(), serviceName = '';
        if (options) {
            if (options.hasOwnProperty('method')) {
                method = options.method;
            }
            if (options.hasOwnProperty('params')) {
                params = options.params;
            }
            if (options.hasOwnProperty('jsonrpc')) {
                jsonrpc = options.jsonrpc;
            }
            if (options.hasOwnProperty('id')) {
                id = options.id;
            }
            if (options.hasOwnProperty('serviceName')) {
                serviceName = options.serviceName;
            }
        }

        requestData.id = id;
        requestData.method = method;
        requestData.params = params;
        requestData.jsonrpc = jsonrpc;
        requestData.serviceName = serviceName;


        //请求数据进行json 序列化
        var requestDataStr = JSON.stringify(requestData);
        if (this.method == 'GET') {
            requestData = require('querystring').escape(requestData);
        }

        //http 的请求参数
        var requestOptions = {
            agent: this.agent.globalAgent,
            method: this.method,
            host: this.host,
            port: this.port,
            path: this.path,
            headers: {
                'content-type': (this.method == 'POST') ? 'application/x-www-form-urlencoded' : 'application/json',
                'content-length': Buffer.byteLength(requestDataStr, 'uft8'),
                'Accept-Encoding': 'utf-8',
            },
            auth: ''
        };
        if (this.authNeeded) {
            requestOptions.auth = this.authData;
        }
        if (this.method == 'GET') {
            requestOptions.path = requestOptions.path + requestData;
        }

        var request = this.agent.request(requestOptions);
        request.on('error', function (error: any) {
            callback(error, undefined);
        });
        //接收数据一定需要使用buffer，不然容易出现乱码
        let buffer = [];
        request.on('response', function (response: any) {

            response.on('data', function (bytes: any) {
                buffer.push(bytes);
            });
            response.on('end', function () {
                var error, result;
                var dataBuf = Buffer.concat(buffer);
                var data = dataBuf.toString('utf8');

                if (response.statusCode === 400) {
                    error = new Error('Connection Accepted but error : 400 Bad request Unauthorized - ' + data);
                    callback(error, data);
                }
                else if (response.statusCode === 401) {
                    error = new Error('Connection Rejected : 401 Unauthorized');
                }
                else if (response.statusCode === 403) {
                    error = new Error('Connection Rejected : 403 Forbidden');
                }
                else if (response.statusCode === 500) {
                    error = new Error('Connection Rejected : 500 Internal server error');
                }
                else if (response.statusCode === 200 || response.statusCode === 304) {
                    if (data.length > 0) {
                        try {
                            result = JSON.parse(data);
                        } catch (err) {
                            error = new Error('Connection Accepted but error JSON :' + err);
                        }
                    }
                } else {
                    error = new Error('Connection Rejected : Unhandled status code ' + response.statusCode + '');
                }
                callback(error, result);
            });
        });

        request.end(requestDataStr);
    }
}

/**
 * json调用远程工厂
 */
@platform.addon("异步工厂", "通过Promise对象进行远程调用的工厂", moduleName)
export class jsonRpcFactory extends platform.proxyFactory {

    //主机IP
    hostname: string;
    //调用路径
    path: string;
    //端口
    port: number;
    //url协议
    protocol: string;

    //json调用客户端
    client: jsonRpcClient;

    constructor(public objectType: new () => any, public url: string, public serviceName: string) {
        super(objectType);
        //解释url
        var urlRes = urlExplain.parse(this.url);
        this.hostname = urlRes.hostname;
        this.port = parseInt(urlRes.port);
        this.path = urlRes.path;
        this.protocol = urlRes.protocol;
    }

    //调用函数
    proxyMethod?(methodName: any, args: any): any {
        this.initJsonClient();
        return new Promise((resolve, reject) => {
            this.client.call({
                method: methodName,
                params: args,
                serviceName: this.serviceName,
            }, (err, res) => {
                if (err) {
                    reject(err);
                } else {
                    resolve(res);
                }
            });
        });
    }

    //初始化jsonrpc 客户端,主要初始化连接参数
    initJsonClient() {
        var config = {
            protocol: this.protocol,
            host: this.hostname,
            port: this.port,
            path: this.path,
            method: 'POST',
        };
        this.client = new jsonRpcClient(config);
    }

}